package com.yuexia.yxim.client.client;

import com.yuexia.yxim.client.sender.ChatSender;
import com.yuexia.yxim.client.sender.LoginSender;
import com.yuexia.yxim.client.command.*;
import com.yuexia.yxim.common.bean.msg.User;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.EventLoop;
import io.netty.util.concurrent.GenericFutureListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * CommandController
 *  命令控制器
 * @author wjp
 * @date 2020/6/1
 */
@Slf4j
@Service("CommandController")
public class CommandController {

    @Autowired
    private ChatConsoleCommand ChatConsoleCommand;

    @Autowired
    private ClientCommandMenu clientCommandMenu;

    @Autowired
    private LoginConsoleCommand loginConsoleCommand;

    @Autowired
    private LogoutConsoleCommand logoutConsoleCommand;

    @Autowired
    private LoginSender loginSender;

    @Autowired
    private ChatSender chatSender;

    @Autowired
    private NettyClient nettyClient;

    private Map<String, BaseCommand> commandMap;

    private Channel channel;
    //会话类
    private ClientSession session;

    //连接开关
    private boolean connectFlag = false;

    private boolean isConnectFlag = false;

    private String menuString;
    private User user;

    GenericFutureListener<ChannelFuture> closeListener = (ChannelFuture f) -> {

        log.info("连接已经断开" + new Date());

        channel = f.channel();

        //创建会话
        ClientSession clientSession = channel.attr(ClientSession.SESSION_KEY).get();
        clientSession.close();

        //唤醒用户线程
        notifyCommandThread();
    };

    //netty建立连接之后，增加一个监听异步任务完成的监听器
    GenericFutureListener<ChannelFuture> connectedlistener = (ChannelFuture f) -> {
        final EventLoop eventLoop = f.channel().eventLoop();

        if (!f.isSuccess()) {
            log.info("连接失败，在10s后尝试重连");
            eventLoop.schedule(() -> nettyClient.doConnect(), 10, TimeUnit.SECONDS);

            connectFlag = false;
        }else {
            connectFlag = true;

            log.info("服务器连接成功");

            Channel channel = f.channel();

            //创建会话
            session = new ClientSession(channel);
            session.setConnected(true);
            channel.closeFuture().addListener(closeListener);

            //唤醒用户线程
            notifyCommandThread();
        }
    };

    private synchronized void notifyCommandThread() {
        this.notify();
    }

    public void startCommandThread() throws InterruptedException {
        Thread.currentThread().setName("命令线程");

        while (true) {
            //建立连接
            while (!connectFlag) {
                //开始连接
                startConnectServer();
                waitCommandThread();
            }

            //处理命令
            while (null != session && session.isConnected()) {
                Scanner scanner = new Scanner(System.in);

                clientCommandMenu.exec(scanner);
                String key = clientCommandMenu.getCommandInput();

                //取到命令收集类pojo
                BaseCommand command = commandMap.get(key);

                switch (key) {
                    case LoginConsoleCommand.KEY:
                        command.exec(scanner);
                        startLogin((LoginConsoleCommand)command);
                        break;
                    default:
                        System.out.println("命令错误...");
                        break;
                }
            }
        }
    }

    /**
     * 开始登录
     * @param command
     */
    private void startLogin(LoginConsoleCommand command) {

        //登录
        if (!isConnectFlag) {
            log.info("连接异常，请重新连接");
            return;
        }
        User user = new User();
        user.setUid(command.getUserName());
        user.setToken(command.getPassword());
        user.setDevId("1111");

        loginSender.setUser(user);
        loginSender.setSession(session);
        loginSender.sendLoginMsg();
    }

    /**
     * 发送单聊消息
     */
    private void startOneChat(ChatConsoleCommand chatConsoleCommand) {
        if (!isLogin()) {
            log.error("还没有登录！");
            return;
        }

        chatSender.setSession(session);
        chatSender.setUser(user);
        chatSender.sendMsg(chatConsoleCommand.getToUserId(), chatConsoleCommand.getMessage());

    }

    private void waitCommandThread() {

    }

    private void startConnectServer() {

    }

    private boolean isLogin() {
        if (null == session) {
            log.info("session is null");
            return false;
        }
        return session.isLogin();
    }

    public void initCommandMap() {
        commandMap = new HashMap<>();
        commandMap.put(clientCommandMenu.getKey(), clientCommandMenu);
        commandMap.put(ChatConsoleCommand.getKey(), ChatConsoleCommand);
        commandMap.put(loginConsoleCommand.getKey(), loginConsoleCommand);
        commandMap.put(logoutConsoleCommand.getKey(), logoutConsoleCommand);

        Set<Map.Entry<String, BaseCommand>> entries = commandMap.entrySet();
        Iterator<Map.Entry<String, BaseCommand>> iterator = entries.iterator();

        StringBuilder menus = new StringBuilder();
        menus.append("[menu] ");

        while (iterator.hasNext()) {
            BaseCommand command = iterator.next().getValue();
            menus.append(command.getKey())
                    .append("->")
                    .append(command.getTip())
                    .append("|");
        }
        menuString = menus.toString();
        clientCommandMenu.setAllCommandsShow(menuString);
    }
}
